#include "./../inc/main.h"

Touch *Touch::m_instance = NULL;
int Touch::fd = -1;

Touch::Touch()
{
    this->fd = open(TOUCH_PATH, O_RDONLY);
    if (this->fd == -1)
    {
        perror("[error] touch open");
    }
}

Touch::~Touch()
{
}

Touch *Touch::instance()
{
    if (m_instance == NULL)
    {
        m_instance = new Touch();
    }
    return m_instance;
}

void Touch::del_instance()
{
    if (m_instance != NULL)
    {
        ::close(fd);
        delete m_instance;
        m_instance = NULL;
        fd = -1;
    }
}

void Touch::wait(Point &p)
{

    while (1)
    {
        struct input_event info;
        // 读取触摸事件坐标
        read(this->fd, &info, sizeof(struct input_event));
        // 判断当前发生的是触摸屏事件,接着判断触发的是X轴事件
        if (info.type == EV_ABS && info.code == ABS_X)
        {
            p.setX(info.value * 800 / 1024);
        }
        // 判断当前发生的是触摸屏事件,接着判断触发的是Y轴事件
        if (info.type == EV_ABS && info.code == ABS_Y)
        {
            p.setY(info.value * 480 / 600);
        }
        // 松开的时候退出循环
        if (info.type == EV_KEY && info.code == BTN_TOUCH && info.value == 0)
        {

            break;
        }
    }
}

// 非阻塞式触摸检测
bool Touch::checkTouch(Point &p)
{
    fd_set readfds;
    struct timeval timeout;
    
    FD_ZERO(&readfds);
    FD_SET(this->fd, &readfds);
    
    timeout.tv_sec = 0;
    timeout.tv_usec = 0;
    
    int ret = select(this->fd + 1, &readfds, NULL, NULL, &timeout);
    
    if (ret > 0 && FD_ISSET(this->fd, &readfds))
    {
        while (true)
        {
            struct input_event info;
            ssize_t len = read(this->fd, &info, sizeof(struct input_event));
            if (len != sizeof(struct input_event))
            {
                break;
            }
            
            // 更新坐标
            if (info.type == EV_ABS && info.code == ABS_X)
            {
                p.setX(info.value * 800 / 1024);
            }
            if (info.type == EV_ABS && info.code == ABS_Y)
            {
                p.setY(info.value * 480 / 600);
            }
            
            if (info.type == EV_KEY && info.code == BTN_TOUCH && info.value == 0)
            {
                return true;
            }
        }
    }
    
    return false;
}

// 重置触摸状态，清空残留事件
void Touch::reset()
{
    fd_set readfds;
    struct timeval timeout;
    
    // 循环读取所有残留事件，直到缓冲区为空
    while (true)
    {
        FD_ZERO(&readfds);
        FD_SET(this->fd, &readfds);
        
        // 非阻塞检查：立即返回是否有数据
        timeout.tv_sec = 0;
        timeout.tv_usec = 0;
        
        int ret = select(this->fd + 1, &readfds, NULL, NULL, &timeout);
        if (ret <= 0)
        {
            break; // 无更多数据可读，退出循环
        }
        
        // 读取并丢弃事件
        if (FD_ISSET(this->fd, &readfds))
        {
            struct input_event info;
            ssize_t len = read(this->fd, &info, sizeof(struct input_event));
            if (len != sizeof(struct input_event))
            {
                break;
            }
        }
    }
}